'''
Created on Jun 10, 2012

@author: thomas_dao
'''

from google.appengine.ext import ndb
from google.appengine.ext.ndb import query
from entity.entity import Feed, UserEventList, Follow
from web import util
import logging
from operator import attrgetter
import unique

@ndb.tasklet
def feed_page(feeds, next_curs, more):
    """
    Return dictionary of page, which is ready to print to json
    """
    # Produce story
    stories = []
    current_photo = None # Temp variable
    
    # Although we use get method, it is efficient because
    # all data has been moved into memcache and context cache
    for feed in feeds:
        story = {}
        actor = yield feed.actor.get_async()
        event = yield feed.event.get_async()
        story['actor'] = util.ndb_to_dict(actor)
        story['event'] = util.ndb_to_dict(event)
        story['created_time'] = feed.created_time.isoformat()
        
        if feed.feed_type == "POST":
            post = yield feed.post.get_async()
            story['story'] = post.post
            story['type'] = 'post'
            
        
        elif feed.feed_type == "PHOTO":
            photo = yield feed.photo.get_async()
            # If last story is photo, and this is another photo
            # of the same album, group it
            last_story = None
            if len(stories) > 0:
                last_story = stories[-1]
            if last_story is not None and \
               current_photo is not None and \
               last_story['type'] == 'photo' and \
               current_photo.album == photo.album and \
               current_photo.author == photo.author:
                # Append photos
                last_story['photos'].append(photo.url)
            else:
                # Create new story, then add to stories list
                story['type'] = 'photo'
                story['story'] = "Actor added photo"
                story['photos'] = []
                story['photos'].append(photo.url)
            
            current_photo = photo
                
            
        elif feed.feed_type == "EVENT":
            story['story'] = "Actor created event"
            story['type'] = 'event'
                
        if 'type' in story:
            stories.append(story)
    
    # Render
    page = {}
    page['cursor'] = next_curs.urlsafe()
    page['stories'] = stories
    page['more'] = more
    raise ndb.Return(page)


@ndb.tasklet
def get_feeds(user_key, category_key=None, **q_options):
    """
    A Feed is relevant if:
    1) One or more user (actor/participants in post) in the feed is within Follow list
    2) The event is in UserEventList
    """
    # Get event that user watched and all other followees
    ((event_feeds, event_nextcurs, event_more),
     (friend_feeds, friend_nextcurs, friend_more)) = yield (get_event_feeds(user_key, category_key=None, **q_options),
                                                            get_friend_feeds(user_key, category_key=None, **q_options))
    
    feeds = event_feeds + friend_feeds
    #feeds_set = set(feeds)
    feeds = unique.unique(feeds)
    feeds = sorted(feeds, key=attrgetter('created_time'), reverse=True)
    logging.info(feeds)
    next_curs = None
    more = False
    if feeds[-1] == event_feeds[-1]:
        next_curs = event_nextcurs
        more = event_more
    else:
        next_curs = friend_nextcurs
        more = friend_more
        
    # Get results
    page = yield feed_page(feeds, next_curs, more)            
    raise ndb.Return(page)


@ndb.tasklet
def get_event_feeds(user_key, category_key=None, **q_options):
    # Get event that user watched
    qry = UserEventList.query(UserEventList.user == user_key)
    user_event_list = yield qry.fetch_async(**q_options)
    event_key_list = []
    for user_event in user_event_list:
        event_key_list.append(user_event.event)
    logging.info(event_key_list)
    
    if category_key:
        qry = Feed.query(Feed.event_category==category_key).order(-Feed.created_time)
    else:
        qry = Feed.query().order(-Feed.created_time)
        
    if event_key_list and len(event_key_list)>0:
        qry = qry.filter(Feed.event.IN(event_key_list))
    feeds, next_curs, more = yield qry.fetch_page_async(20, **q_options)
    raise ndb.Return(feeds, next_curs, more)


@ndb.tasklet
def get_friend_feeds(user_key, category_key=None, **q_options):
    # Get all other followees that current user follow
    qry = Follow.query(Follow.follower == user_key)
    follow_list = yield qry.fetch_async(**q_options)
    followee_list = []
    for follow in follow_list:
        followee_list.append(follow.followee)
    logging.info(followee_list)
    
    # Load feeds related to followees
    # Currently only retrieve feeds that have actor in the follow list
    if category_key:
        qry = Feed.query(Feed.event_category==category_key).order(-Feed.created_time)
    else:
        qry = Feed.query().order(-Feed.created_time)

    if followee_list and len(followee_list)>0:
        qry = qry.filter(Feed.actor.IN(followee_list))
    feeds, next_curs, more = yield qry.fetch_page_async(20, **q_options)
    raise ndb.Return(feeds, next_curs, more)
